package yu.code.yurpc.server.tcp;

import io.vertx.core.buffer.Buffer;
import yu.code.yurpc.model.RpcRequest;
import yu.code.yurpc.model.RpcResponse;
import yu.code.yurpc.protocol.ProtocolConstant;
import yu.code.yurpc.protocol.ProtocolMessage;
import yu.code.yurpc.protocol.ProtocolMessageSerializerEnum;
import yu.code.yurpc.protocol.ProtocolMessageTypeEnum;
import yu.code.yurpc.serializer.Serializer;
import yu.code.yurpc.serializer.SerializerFactory;

import java.io.IOException;

/**
 * 解码器
 */
public class ProtocolMessageDecoder {
    public static ProtocolMessage<?> decode(Buffer buffer) throws IOException {
        //分别从指定位置读出buffer
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        byte magic = buffer.getByte(0);
        if (magic != ProtocolConstant.PROTOCOL_MAGIC) {
            throw new IOException("消息 magic 非法");
        }
        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getLong(5));
        header.setBodyLength(buffer.getInt(13));
        //解决粘包问题，读指定长度数据
        byte[] bodyBytes = buffer.getBytes(17, 17 + header.getBodyLength());
        //解析消息体
        ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getEnumByKey(header.getSerializer());
        if (serializerEnum == null) {
            throw new RuntimeException("序列化消息的协议不存在");
        }
        ProtocolMessageTypeEnum messageTypeEnum = ProtocolMessageTypeEnum.getByKey(header.getType());
        if (messageTypeEnum == null) {
            throw new RuntimeException("消息类型不存在");
        }
        Serializer serializer = SerializerFactory.getInstance(serializerEnum.getValue());
        switch (messageTypeEnum) {
            case REQUEST: {
                RpcRequest rpcRequest = serializer.deserialize(bodyBytes, RpcRequest.class);
                return new ProtocolMessage<>(header, rpcRequest);
            }
            case RESPONSE: {
                RpcResponse rpcResponse = serializer.deserialize(bodyBytes, RpcResponse.class);
                return new ProtocolMessage<>(header, rpcResponse);
            }
            case HEART_BEAT:
            case OTHERS:
            default:
                throw new RuntimeException("消息类型不支持");
        }
    }
}
